package com.user.handler;

import com.user.enums.LoginType;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * 策略模式
 * 不同的 LoginHandler 实现（如用户名密码登录、手机验证码登录）提供了不同的算法实现
 */
@Component
@RequiredArgsConstructor
public class LoginFactory implements ApplicationContextAware {
    private final AuthenticationSuccessHandler successHandler;
    private final AuthenticationFailureHandler failureHandler;
    private ApplicationContext applicationContext;

    public void login(HttpServletRequest request, HttpServletResponse response, Object principal, Object credentials, LoginType loginType) throws ServletException, IOException {
        try {
            LoginHandler loginHandler = applicationContext.getBean(loginType.getValue(), LoginHandler.class);
            UserDetails userDetails = loginHandler.login(principal, credentials);
            Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, credentials, userDetails.getAuthorities());
            successHandler.onAuthenticationSuccess(request,response,authentication);
        } catch (AuthenticationException e) {
            failureHandler.onAuthenticationFailure(request,response,e);
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
